package com.own.business.system.user.phone.business.service.impl;

import com.own.business.login.phone.core.service.LoginPhoneService;
import com.own.business.system.account.business.service.SystemAccountService;
import com.own.business.system.account.common.em.AccountType;
import com.own.business.system.user.business.service.SystemRegisterService;
import com.own.business.system.user.business.service.SystemUserInfoService;
import com.own.business.system.user.business.service.SystemUserService;
import com.own.business.system.user.common.exception.SystemUserException;
import com.own.business.system.user.phone.business.method.SystemUserPhoneRegisterMethodHook;
import com.own.business.system.user.phone.business.service.SystemUserPhoneLoginService;
import com.own.component.common.exception.BusinessSimpleException;
import com.own.component.store.core.util.LockStoreUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;

/**
 * SystemUserPhoneLoginServiceImpl
 *
 * @author chenxueli
 * @date 2023-06-25 22:59:00
 */
@Slf4j
@Service
public class SystemUserPhoneLoginServiceImpl implements
        SystemUserPhoneLoginService,
        LoginPhoneService {

    @Resource
    private SystemAccountService systemAccountService;
    @Resource
    private SystemRegisterService systemRegisterService;
    @Resource
    private SystemUserService systemUserService;

    @Resource
    private SystemUserPhoneRegisterMethodHook systemUserPhoneRegisterMethodHook;

    @Resource
    private SystemUserInfoService systemUserInfoService;

    @Resource
    private LockStoreUtil lockStoreUtil;

    /**
     * 登录表单
     *
     * @param phone    手机号
     * @param password 密码
     * @param type     账号类型 1=普通用户 2=管理员
     * @return 登录的用户id信息
     */
    @Override
    public Long login(String phone, String password, int type) {
        // 去账号表查询账号的信息
        var po = systemAccountService.get(phone, AccountType.PHONE, type);
        if (po != null) {
            if (po.getEnable() == 0) {
                throw new SystemUserException("账号已被禁用");
            }
            return po.getFkUserId();
        }
        // 调用前置信息
        var userId = systemUserPhoneRegisterMethodHook.before(phone);
        if (userId == null) {
            // 注册账号信息
            var vo = systemRegisterService.register(phone, null, AccountType.PHONE.type(), type);
            // 设置账号的手机号信息
            systemUserInfoService.updatePhone(vo.getId(), phone);
            // 如果存在密码的情况需要使用密码再注册一次账号
            if (StringUtils.isNotBlank(password)) {
                systemRegisterService.register(vo.getId(), phone, password, AccountType.TEXT.type(), type);
            }
            // 返回用户id
            return vo.getId();
        }
        return userId;
    }

    /**
     * 退出登录
     *
     * @return 是否退出成功
     */
    @Override
    public boolean loginOut() {
        return true;
    }

    /**
     * 账号绑定手机号
     *
     * @param userId 用户id
     * @param phone  手机号
     */
    @Override
    public void bind(Long userId, String phone) {
        lockStoreUtil.tryLock("bind:phone" + phone, () -> {
            // 根据用户id查询信息
            var user = systemUserService.getPoById(userId);
            // 查询待绑定的手机号是否已经绑定过账号了
            var po = systemAccountService.get(phone, AccountType.PHONE, user.getType());
            if (po != null) {
                throw new SystemUserException("该手机号已经被绑定了，请先解绑");
            }
            // 创建新的账号
            systemAccountService.save(phone, AccountType.PHONE, user.getType(), userId);
            // 添加到用户信息
            systemUserInfoService.updatePhone(userId, phone);
        }, () -> {
            throw new BusinessSimpleException("当前手机号有人正在绑定，请稍后再试");
        });
    }

    /**
     * 账号换绑手机号
     *
     * @param userId 用户id
     * @param phone  手机号
     */
    @Override
    public void changeBind(Long userId, String phone) {
        lockStoreUtil.lock("bind:phone" + phone, () -> {
            // 根据用户id查询信息
            var user = systemUserService.getPoById(userId);
            // 查询待绑定的手机号是否已经绑定过账号了
            var po = systemAccountService.get(phone, AccountType.PHONE, user.getType());
            if (po != null) {
                throw new SystemUserException("该手机号已经被绑定了，请先解绑");
            }
            // 直接删除手机号登录的验证信息
            systemAccountService.remove(userId, AccountType.PHONE);
            // 创建新的账号
            systemAccountService.save(phone, AccountType.PHONE, user.getType(), userId);
            // 添加到用户信息
            systemUserInfoService.updatePhone(userId, phone);
        });
    }

    /**
     * 解绑手机号
     *
     * @param userId 用户id
     */
    @Override
    public void unbind(Long userId) {
        // 判断有几个账号信息
        var count = systemAccountService.count(userId);
        if (count <= 1) {
            throw new SystemUserException("当前账号无法解绑手机号，请先设置登录密码后解绑");
        }
        systemAccountService.remove(userId, AccountType.PHONE);
        // 修改到用户信息
        systemUserInfoService.updatePhone(userId, null);
    }

}
